home *** CD-ROM | disk | FTP | other *** search
/ 10,000 Great Games / 10,000 Great Games.iso / Product / 66 / data1.cab / Source_Files / Src / MakeRandom.cpp < prev    next >
C/C++ Source or Header  |  2000-01-16  |  6KB  |  273 lines

  1. #include "stdafx.h"
  2.  
  3. #define MAX_TRIES    30
  4.  
  5. class cOccupied : public cBox
  6. {
  7. public:
  8.     cOccupied(cOccupied **list, int x1, int y1, int x2, int y2, cProperties *p);
  9.  
  10.     static int jumpable(int x, int y, cProperties *p);
  11.     static int occupy(int x, int y, cProperties *p);
  12.  
  13.     cProperties *what;
  14. };
  15.  
  16. static cOccupied *game_occ = 0, *back_occ = 0;
  17.  
  18. cOccupied::cOccupied(cOccupied **list, int _x1, int _y1, int _x2, int _y2, cProperties *p)
  19. {
  20.     add((cList **)list);
  21.  
  22.     x1 = _x1, y1 = _y1, x2 = _x2, y2 = _y2;
  23.  
  24.     what = p;    
  25. }
  26.  
  27. int cOccupied::jumpable(int x, int y, cProperties *p)
  28. {
  29.     ASSERT (p->objtype != 0);
  30.  
  31.     // Get list to check with
  32.  
  33.     cOccupied *list = *p->objtype->surface == game_surface? game_occ : back_occ;
  34.  
  35.     // Force jumpable when list is empty
  36.  
  37.     if (list == 0)
  38.         return TRUE;
  39.  
  40.     // Get coordinates of bounding box
  41.  
  42.     int x1 = x + p->bbox.x1,
  43.         y1 = y - p->bbox.y1,
  44.         x2 = x + p->bbox.x2;
  45.  
  46.     // Check if any other platform is jumpable from this platform
  47.  
  48.     for (cOccupied *o = list; o != 0; o = (cOccupied *)o->next)
  49.     {
  50.         if (y1 == o->y1 && o->x1 - x2 <= LEVEL_HJUMP && x1 - o->x2 <= LEVEL_HJUMP)
  51.             return TRUE;
  52.  
  53.         if (abs(y1 - o->y1) <= LEVEL_VJUMP && o->x1 - x2 <= LEVEL_HJUMP / 2 && x1 - o->x2 <= LEVEL_HJUMP / 2)
  54.             return TRUE;
  55.     }
  56.  
  57.     // None found
  58.  
  59.     return FALSE;
  60. }
  61.  
  62. int cOccupied::occupy(int x, int y, cProperties *p)
  63. {
  64.     ASSERT (p->objtype != 0);
  65.  
  66.     cOccupied **list = *p->objtype->surface == game_surface? &game_occ : &back_occ;
  67.  
  68.     int x1 = x + p->bbox.x1,
  69.         y1 = y - p->bbox.y1,
  70.         x2 = x + p->bbox.x2,
  71.         y2 = y - p->bbox.y2;
  72.  
  73.     // If not forced to occupy check if there is another object in the list
  74.     // occupying the same space
  75.  
  76.     if (p->no_overlap)
  77.         for (cOccupied *o = *list; o != 0; o = (cOccupied *)o->next)
  78.             if (x1 < o->x2 && o->x1 < x2 && y2 < o->y1 && o->y2 < y1)
  79.                 return FALSE;
  80.  
  81.     // Add to list
  82.  
  83.     new cOccupied(list, x1, y1, x2, y2, p);
  84.  
  85.     // Create real object
  86.  
  87.     cObjectTypes::make(x, y, p, TRUE);
  88.  
  89.     return TRUE;
  90. }
  91.  
  92. static int determine_number(int r)
  93. {
  94.     // This is assumed now
  95.  
  96.     ASSERT (r >= 0 && r <= 300);
  97.  
  98.     // Return number of things to create on this level
  99.  
  100.     if (r < 100)
  101.         return rnd(100) < r? 1 : 0;
  102.     else
  103.         return (3 * r / 4 + rnd(r / 2) + 50) / 100;
  104. }
  105.  
  106. static void make_platforms()
  107. {
  108.     // Create random list
  109.  
  110.     cRandomList platforms(PLACEMENT_PLATFORM);
  111.  
  112.     if (platforms.is_empty() || random_placement_platform <= 0)
  113.     {
  114.         info("Warning: No platforms created!");
  115.         return;
  116.     }
  117.  
  118.     // Variable to indicate impossible jump
  119.  
  120.     int jumpable_warning = FALSE;
  121.  
  122.     // Loop through all levels
  123.  
  124.     for (int l = LEVEL_VJUMP; l < LEVEL_SIZE; l += LEVEL_VJUMP)
  125.     {
  126.         // Determine number of platforms to add
  127.  
  128.         int n = determine_number(random_placement_platform);
  129.  
  130.         // Case no platforms on this level
  131.  
  132.         if (n <= 0)
  133.         {
  134.             if (random_placement_platform >= 100)
  135.                 n = 1;
  136.             else
  137.                 jumpable_warning = TRUE;
  138.         }
  139.  
  140.         // Create platforms
  141.  
  142.         while (n > 0)
  143.         {
  144.             // Get random object
  145.             
  146.             cProperties *p = platforms.get_weighted_random();
  147.             
  148.             // Try to add this platform
  149.             
  150.             for (int tries = 0; tries < 2 * MAX_TRIES; tries++)
  151.             {
  152.                 int x = -p->bbox.x1 + GAME_EDGE + rnd(GAME_DX - 2 * GAME_EDGE - (p->bbox.x2 - p->bbox.x1)),
  153.                     y = l + p->bbox.y1;
  154.                 
  155.                 if ((tries >= MAX_TRIES || cOccupied::jumpable(x, y, p)) && cOccupied::occupy(x, y, p))
  156.                     break;
  157.             } 
  158.  
  159.             n--;
  160.         }
  161.     }
  162.  
  163.     if (jumpable_warning)
  164.         info("Warning: Level contains impossible jumps!");
  165. }
  166.  
  167. static void make_on_platform()
  168. {
  169.     cRandomList on_platform(PLACEMENT_ON_PLATFORM);
  170.  
  171.     if (on_platform.is_empty() || random_placement_on <= 0)
  172.         return;
  173.  
  174.     for (cOccupied *o = game_occ; o != 0; o = (cOccupied *)o->next)
  175.         if (o->what->placement == PLACEMENT_PLATFORM)
  176.             for (int n = determine_number(random_placement_on); n > 0; n--)
  177.             {
  178.                 cProperties *p = on_platform.get_weighted_random();
  179.                 
  180.                 if (p->bbox.x2 - p->bbox.x1 >= o->x2 - o->x1
  181.                     || o->y2 < GAME_DY
  182.                     || o->y1 - p->bbox.y1 > LEVEL_SIZE)
  183.                     continue;
  184.                 
  185.                 for (int tries = 0; tries < MAX_TRIES; tries++)
  186.                 {
  187.                     int x = o->x1 - p->bbox.x1 + rnd(o->x2 - o->x1 - (p->bbox.x2 - p->bbox.x1)),
  188.                         y = o->y1 + p->bbox.y2;
  189.                     
  190.                     if (cOccupied::occupy(x, y, p))
  191.                         break;
  192.                 }
  193.             }    
  194. }
  195.  
  196. static void make_between_platforms()
  197. {
  198. }
  199.  
  200. static void make_under_platform()
  201. {
  202.     cRandomList under_platform(PLACEMENT_UNDER_PLATFORM);
  203.  
  204.     if (under_platform.is_empty() || random_placement_under <= 0)
  205.         return;
  206.  
  207.     for (cOccupied *o = game_occ; o != 0; o = (cOccupied *)o->next)
  208.         if (o->what->placement == PLACEMENT_PLATFORM)
  209.             for (int n = determine_number(random_placement_under); n > 0; n--)
  210.             {
  211.                 cProperties *p = under_platform.get_weighted_random();
  212.     
  213.                 if (p->bbox.x2 - p->bbox.x1 >= o->x2 - o->x1                
  214.                     || o->y2 < GAME_DY
  215.                     || o->y1 - p->bbox.y1 > LEVEL_SIZE)
  216.                     continue;
  217.                 
  218.                 for (int tries = 0; tries < MAX_TRIES; tries++)
  219.                 {
  220.                     int x = o->x1 - p->bbox.x1 + rnd(o->x2 - o->x1 - (p->bbox.x2 - p->bbox.x1)),
  221.                         y = o->y2 + p->bbox.y1;
  222.                     
  223.                     if (cOccupied::occupy(x, y, p))
  224.                         break;
  225.                 }
  226.             }
  227. }
  228.  
  229. static void make_any()
  230. {
  231.     cRandomList any(PLACEMENT_ANY);
  232.  
  233.     if (any.is_empty() || random_placement_any <= 0)
  234.         return;
  235.  
  236.     for (int n = LEVEL_VLEVELS * random_placement_any / 100; n > 0; n--)
  237.     {
  238.         cProperties *p = any.get_weighted_random();
  239.  
  240.         for (int tries = 0; tries < LEVEL_VLEVELS; tries++)
  241.         {
  242.             int x = -p->bbox.x1 + GAME_EDGE + rnd(GAME_DX - 2 * GAME_EDGE - (p->bbox.x2 - p->bbox.x1)),
  243.                 y = GAME_DY + p->bbox.y2 + rnd((*p->objtype->surface)->total_h - GAME_DY - (p->bbox.y2 - p->bbox.y1));
  244.  
  245.             if (cOccupied::occupy(x, y, p))
  246.                 break;
  247.         } 
  248.     }    
  249. }
  250.  
  251. void make_level()
  252. {
  253.     // First create platforms and stuff between platforms
  254.  
  255.     make_platforms();
  256.     make_between_platforms();
  257.  
  258.     // Then create rest of shit
  259.  
  260.     make_on_platform();
  261.     make_under_platform();    
  262.     make_any();
  263.  
  264.     // Remove occupied lists
  265.  
  266.     back_occ->delete_list();
  267.     game_occ->delete_list();    
  268.  
  269.     // Create editables
  270.  
  271.     cEditable::make_editables();
  272. }
  273.